// collector/collector.go
package collector

import (
	"context"
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	config "csudata.com/zqpool/src/config"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promauto"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

var (
	// 某个连接池的后端连接数目
	BackendConnections = promauto.NewGaugeVec(prometheus.GaugeOpts{
		Namespace: "zqpool",
		// Subsystem: "gauge",
		Name: "backend_connections",
		Help: "Number of backend connections for a pool.",
	}, []string{"pool_id"})

	// 某个连接池的活跃后端连接数目
	AcitveBackendConnections = promauto.NewGaugeVec(prometheus.GaugeOpts{
		Namespace: "zqpool",
		Name:      "active_backend_connections",
		Help:      "Number of active backend connections for a pool.",
	}, []string{"pool_id"})

	// 某个连接池的前端连接数目
	FeConnCount = promauto.NewGaugeVec(prometheus.GaugeOpts{
		Namespace: "zqpool",
		// Subsystem: "gauge",
		Name: "frontend_connections",
		Help: "Number of frontend connections for a pool.",
	}, []string{"pool_id"})

	// 某个连接池的活动前端连接数目
	// ActiveFrontendConnections = promauto.NewGaugeVec(prometheus.GaugeOpts{
	FeActiveCount = promauto.NewGaugeVec(prometheus.GaugeOpts{
		Namespace: "zqpool",
		// Subsystem: "gauge",
		Name: "active_frontend_connections",
		Help: "Number of active frontend connections for a pool.",
	}, []string{"pool_id"})

	// 某个连接池的请求总数
	TotalRequests = promauto.NewCounterVec(prometheus.CounterOpts{
		Namespace: "zqpool",
		Name:      "total_requests",
		Help:      "Total number of requests for a pool.",
	}, []string{"pool_id"})

	// 某个连接池的简单查询总数
	SimpleQueries = promauto.NewCounterVec(prometheus.CounterOpts{
		Namespace: "zqpool",
		Name:      "total_simple_queries",
		Help:      "Total simple queries for a pool.",
	}, []string{"pool_id"})

	// 某个连接池的扩展查询总数
	ExtendedQueries = promauto.NewCounterVec(prometheus.CounterOpts{
		Namespace: "zqpool",
		Name:      "total_extended_queries",
		Help:      "Total extended queries for a pool.",
	}, []string{"pool_id"})

	// 某个连接池的后端连接数被占满的次数
	BackendConnectionLimitReachedTimes = promauto.NewCounterVec(prometheus.CounterOpts{
		Namespace: "zqpool",
		Name:      "backend_connection_limit_reached_times",
		Help:      "The backend connection limit has been reached multiple times.",
	}, []string{"pool_id"})
)

func UpdateBackendConnections(labelValue string, value float64) {
	BackendConnections.WithLabelValues(labelValue).Set(value)
}

func UpdateAcitveBackendConnections(labelValue string, value float64) {
	AcitveBackendConnections.WithLabelValues(labelValue).Set(value)
}

// func FrontendConnectionsIncrease(labelValue string) {
// 	FeConnCount.With(prometheus.Labels{"pool_id": labelValue}).Inc()
// }

// func FrontendConnectionsDecrease(labelValue string) {
// 	FeConnCount.With(prometheus.Labels{"pool_id": labelValue}).Dec()
// }

// func ActiveFrontendConnectionsIncrease(labelValue string) {
// 	FeActiveConns.With(prometheus.Labels{"pool_id": labelValue}).Inc()
// }

//	func ActiveFrontendConnectionsDecrease(labelValue string) {
//		FeActiveConns.With(prometheus.Labels{"pool_id": labelValue}).Dec()
//	}

func IncreaseTotalRequests(labelValue string) {
	TotalRequests.With(prometheus.Labels{"pool_id": labelValue}).Inc()
}

func IncreaseSimpleQueries(labelValue string) {
	SimpleQueries.With(prometheus.Labels{"pool_id": labelValue}).Inc()
}

func IncreaseExtendedQueries(labelValue string) {
	ExtendedQueries.With(prometheus.Labels{"pool_id": labelValue}).Inc()
}

func IncreaseBackendConnectionLimitReachedTimes(labelValue string) {
	BackendConnectionLimitReachedTimes.With(prometheus.Labels{"pool_id": labelValue}).Inc()
}

func StartPromServer() {
	_, cancel := context.WithCancel(context.Background())
	defer cancel()

	port := config.Get("exporter_port")
	if port == "" {
		log.Println("exporter_port not set in configuration, set port of Exporter to '9816'.")
		port = "9816"
	}

	srv := &http.Server{
		Addr:    ":" + port,
		Handler: promhttp.Handler(),
	}

	sigint := make(chan os.Signal, 1)
	signal.Notify(sigint, syscall.SIGINT, syscall.SIGTERM)

	go func() {
		<-sigint
		cancel()
		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
		defer cancel()
		if err := srv.Shutdown(ctx); err != nil {
			// 如果 Shutdown 不成功，就强制关闭
			log.Printf("Server forced to shutdown: %v", err)
		}
	}()
	log.Fatal(srv.ListenAndServe())
}
